package com.commbizobj.money;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Locale;

import org.junit.Before;
import org.junit.Test;

public class MoneyTest {

    // CNY has 2 decimal places while JPY has 0
    private Money priceCNY, priceJPY;
    
    @Before
    public void setUp() throws Exception {
        priceCNY = Money.getInstanceByDecimalValue("CNY", 12.50);
        priceJPY = Money.getInstanceByDecimalValue("JPY", 1250);
    }
    
    @Test
    public final void testGetDecimalValue() {
        Money priceCNY2 = Money.getInstanceByValue("CNY", 1250);
        assertEquals(priceCNY.getDecimalValue(), priceCNY2.getDecimalValue(), 2);
        Money priceJPY2 = Money.getInstanceByValue("JPY", 1250);
        assertEquals(priceJPY.getDecimalValue(), priceJPY2.getDecimalValue(), 2);
    }

    @Test
    public final void testGetDecimalValueFormatted() {
        assertEquals("12.50", priceCNY.getDecimalValueFormatted());
    }

    @Test
    public final void testAdd() {
        Money priceCNY2 = Money.getInstanceByDecimalValue("CNY", 12.25);
        Money result = priceCNY2.add(priceCNY);
        assertEquals(24.75, result.getDecimalValue(), 2);
    }
    
    @Test(expected = UnsupportedOperationException.class)
    public final void testAddException() {
        priceCNY.add(priceJPY);
    }
    
    @Test
    public final void testSubstract() {
        Money priceCNY2 = Money.getInstanceByDecimalValue("CNY", 12.25);
        Money result = priceCNY.substract(priceCNY2);
        assertEquals(0.25, result.getDecimalValue(), 2);
        priceCNY2 = Money.getInstanceByDecimalValue("CNY", 25);
        result = priceCNY.substract(priceCNY2);
        assertEquals(-12.25, result.getDecimalValue(), 2);
    }

    @Test
    public final void testMultiply() {
        Money result = priceCNY.multiply(4);
        assertEquals(50, result.getDecimalValue(), 2);
    }
    
    @Test(expected = IllegalArgumentException.class)
    public final void testMultiplyException() {
        priceCNY.multiply(-4);
    }

    @Test
    public final void testCompareTo() {
        Money priceCNY2 = Money.getInstanceByDecimalValue("CNY", 12.25);
        assertTrue(priceCNY.compareTo(priceCNY2) > 0);
    }
    
    @Test(expected = UnsupportedOperationException.class)
    public final void testCompareToException() {
        priceCNY.compareTo(priceJPY);
    }

    @Test
    public final void testToString() {
        // This might not hold true under other default locale setting
        assertEquals("CNY 12.50", priceCNY.toString());
        priceCNY.setDecimalValue(-35.35);
        // Negative number
        assertEquals("CNY -35.35", priceCNY.toString());
    }

    @Test
    public final void testToStringLocale() {
        assertEquals("CNY 12.50", priceCNY.toString(new Locale("zh_CN")));
    }

    @Test
    public final void testCloneAndEquals() {
        Money priceCNY2 = priceCNY.clone();
        assertTrue(priceCNY.equals(priceCNY2));
    }

    @Test
    public final void testHashCode() {
        Money priceCNY2 = Money.getInstanceByDecimalValue("CNY", 12.50);
        assertEquals(priceCNY.hashCode(), priceCNY2.hashCode());
        priceCNY2 = Money.getInstanceByDecimalValue("CNY", 12.51);
        assertFalse(priceCNY.hashCode() == priceCNY2.hashCode());
    }
    
}
